package com.itfreer.print.toWord;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Entities;
import org.jsoup.select.Elements;

import com.itextpdf.text.DocumentException;
import com.itfreer.print.TemplateFilePara;
import com.itfreer.print.base.docx4j.Docx4jUtils;
import com.itfreer.print.toWord.HtmlToWord;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import org.docx4j.convert.in.xhtml.XHTMLImporterImpl;
import org.docx4j.model.structure.PageSizePaper;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

/**
 * 定义将html转换为word文档 基于docx4j实现html转换为docx
 */
@Component
public class HtmlToWordImp implements HtmlToWord {

	@Autowired(required = false)
	private TemplateFilePara templateFilePara;

	/**
	 * 将html文件转换为pdf文件
	 * 
	 * @param htmlUrl
	 *            html文件
	 * @param wordFile
	 *            word文件
	 * @throws Exception
	 */
	public void toWord(String htmlUrl, OutputStream wordFile, boolean pageLocation) throws Exception {
		Document doc = url2xhtml(htmlUrl);
		WordprocessingMLPackage wordMLPackage = xhtml2word(doc, pageLocation);
		wordMLPackage.save(wordFile); // 保存到 docx 文件
	}

	/**
	 * 将html文件转换为pdf文件
	 * 
	 * @param htmlUrl
	 *            html文件
	 * @param wordFile
	 *            word文件
	 * @throws Exception
	 */
	public void toWord(InputStream htmlFile, OutputStream wordFile, boolean pageLocation) throws Exception {
		Document doc = input2xhtml(htmlFile);
		WordprocessingMLPackage wordMLPackage = xhtml2word(doc, pageLocation);
		wordMLPackage.save(wordFile); // 保存到 docx 文件
	}

	/**
	 * 基于模板输出word文件
	 * 
	 * @param tempPath
	 *            模板文件路径
	 * @param templateFile
	 *            模板文件
	 * @param data
	 *            模板数据
	 * @param wordFile
	 *            输出word文件
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public void toWord(String tempPath, String templateFile, Object data, OutputStream wordFile, boolean pageLocation)
			throws Exception {
		ByteArrayOutputStream htmlOut = new ByteArrayOutputStream();
		OutputStreamWriter htmlWriter = new OutputStreamWriter(htmlOut, "UTF-8");

		try {
			Configuration freeMarkerconfig = new Configuration();
			freeMarkerconfig.setDirectoryForTemplateLoading(new File(tempPath));
			freeMarkerconfig.setDefaultEncoding("UTF-8");
			Template freeMarkerTemplateerconfig;
			freeMarkerTemplateerconfig = freeMarkerconfig.getTemplate(templateFile, "UTF-8");
			// 往模板中写入数据
			freeMarkerTemplateerconfig.process(data, htmlWriter);
			htmlWriter.flush();
			htmlOut.flush();

			// html流
			ByteArrayInputStream htmlFile = new ByteArrayInputStream(htmlOut.toByteArray());
			toWord(htmlFile, wordFile, pageLocation);

			htmlFile.close();
			htmlWriter.close();
			htmlOut.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} catch (TemplateException e) {
			e.printStackTrace();
			throw e;
		} catch (DocumentException e) {
			e.printStackTrace();
			throw e;
		}
	}

	/**
	 * 将 {@link org.jsoup.nodes.Document} 对象转为
	 * {@link org.docx4j.openpackaging.packages.WordprocessingMLPackage} xhtml to
	 * word
	 *
	 * @param doc
	 * @param pageLocation
	 *            纸张方向问题 true 为横版，false为竖版
	 * @return
	 * @throws Exception
	 */
	protected WordprocessingMLPackage xhtml2word(Document doc, boolean pageLocation) throws Exception {
		WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage(PageSizePaper.valueOf("A4"),
				pageLocation); // A4纸，横版:true
		// 配置中文字体
		Docx4jUtils docx4jUtils = new Docx4jUtils();
		docx4jUtils.configFont(wordMLPackage);
		XHTMLImporterImpl xhtmlImporter = new XHTMLImporterImpl(wordMLPackage);
		// 导入 xhtml
		wordMLPackage.getMainDocumentPart().getContent().addAll(xhtmlImporter.convert(doc.html(), doc.baseUri()));
		return wordMLPackage;
	}

	/**
	 * 将页面转为{@link org.jsoup.nodes.Document}对象，xhtml 格式
	 *
	 * @param url
	 * @return
	 * @throws Exception
	 */
	protected Document url2xhtml(String url) throws Exception {
		// 获得
		Document doc = Jsoup.connect(url).get();
		return optionDocument(doc);
	}

	/**
	 * 将页面转为{@link org.jsoup.nodes.Document}对象，xhtml 格式
	 *
	 * @param url
	 * @return
	 * @throws Exception
	 */
	protected Document input2xhtml(InputStream input) throws Exception {
		// 获得
		Document doc = Jsoup.parse(input, "UTF-8", "");
		return optionDocument(doc);
	}

	/**
	 * 对document进行处理
	 * 
	 * @param doc
	 * @return
	 */
	protected Document optionDocument(Document doc) {
		// 除去所有 script
		for (Element script : doc.getElementsByTag("script")) {
			script.remove();
		}

		// 除去 a 的 onclick，href 属性
		for (Element a : doc.getElementsByTag("a")) {
			a.removeAttr("onclick");
			a.removeAttr("href");
		}

		// 将link中的地址替换为绝对地址
		Elements links = doc.getElementsByTag("link");
		for (Element element : links) {
			String href = element.absUrl("href");
			element.attr("href", href);
		}

		// 转为xhtml格式
		doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml).escapeMode(Entities.EscapeMode.xhtml);
		return doc;
	}

	@Override
	public void toWord(String templateFile, Object data, OutputStream wordFile, boolean pageLocation) throws Exception {
		if (templateFilePara == null) {
			return;
		}

		String tempPath = templateFilePara.getTemplatePath();
		if (!tempPath.contains(":\\") && !tempPath.startsWith("/")) {
			tempPath = this.getClass().getResource("/").getPath() + tempPath;
		}

		toWord(tempPath, templateFile, data, wordFile, pageLocation);
	}

	@Override
	public void toWord(String htmlUrl, OutputStream wordFile) throws Exception {
		this.toWord(htmlUrl, wordFile, false);

	}

	@Override
	public void toWord(InputStream htmlFile, OutputStream wordFile) throws Exception {
		this.toWord(htmlFile, wordFile, false);
	}

	@Override
	public void toWord(String tempPath, String templateFile, Object data, OutputStream wordFile) throws Exception {
		this.toWord(tempPath, templateFile, data, wordFile, false);

	}

	@Override
	public void toWord(String templateFile, Object data, OutputStream wordFile) throws Exception {
		this.toWord(templateFile, data, wordFile, false);

	}
}
